package com.supos.plugin.mojo;


import com.supos.plugin.bean.App;
import com.supos.plugin.bean.Compose;
import com.supos.plugin.bean.Other;
import com.supos.plugin.bean.Vendor;
import com.supos.plugin.util.FreemarkerUtil;
import com.supos.plugin.util.ValidateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;


/**
 * 生成APP配置文件
 * @author <xinwangji@supcon.com>
 * @date 2020年3月31日16:43:24
 */
@Mojo(name="generate")
public class Generate extends AbstractMojo {

    @Parameter(property = "app")
    private App app;

    @Parameter(property = "compose")
    private Compose compose;

    @Parameter(property = "vendor")
    private Vendor vendor;

    @Parameter(property = "other")
    private Other other;

    @Parameter(property = "project.build.directory")
    private String targetPath;

    @Parameter(property = "project.packaging",defaultValue = "jar")
    private String packageing;

    /**
     * 默认生成文件的后缀
     */
    private final static String DEFAULT_SUFFIX = ".yaml";

    public void execute() {
        //参数校验
        ValidateUtil.validate(app);
        ValidateUtil.validate(compose);
        ValidateUtil.validate(vendor);

        System.out.println("app : " + app.toString());
        System.out.println("compose : " + compose.toString());
        System.out.println("vendor : " + vendor.toString());
        System.out.println("other : " + other.toString());

        //输出目录 target/supos
        String projectPath = targetPath + File.separator + "supos" + File.separator;
        System.out.println("projectPath :" + projectPath);

        //相对于name的一个扩展名称,比如中文名
        //当apiVersion = v2alpha1  时   必填
        String showName = app.getShowName();
        String apiVersion = app.getApiVersion();
        if ("v1alpha1".equals(apiVersion)){
            showName = StringUtils.EMPTY;
        } else if ("v2alpha1".equals(apiVersion) && StringUtils.isEmpty(showName)){
            getLog().error(">>>>>>>>>>>>>>>>>打包失败：当apiVersion = v2alpha1时，showName不可为空<<<<<<<<<<<<");
            throw new RuntimeException(">>>>>>>>>>>>>>>>>打包失败：当apiVersion = v2alpha1时，showName不可为空<<<<<<<<<<<<");
        } else {
            showName = "showName: " + showName;
        }

        Map<String,Object> map = new HashMap<>();
        //----------------------封装模板参数----------------------
        //----------------------app.yaml----------------------
        map.put("vendorName",app.getVendorName());//APP开发者或组织的名称
        map.put("name",app.getName());//APP的名称
        String appVersion = app.getAppVersion();
        //截取版本号，比如有0.0.1-SNAPSHOT  取0.0.1
        if (appVersion.indexOf("-") > 1){
            appVersion = appVersion.split("-")[0];
        }
        map.put("appVersion",appVersion);//APP版本
        map.put("description",app.getAppVersion());//APP描述
        map.put("apiVersion",app.getApiVersion());//apiVersion
        map.put("showName",showName);
        map.put("id",app.getVendorName() + "-" + app.getName());// vendorName + “-” + name
        //----------------------compose.yaml----------------------
        map.put("replicas",compose.getReplicas());
        map.put("containersName",compose.getContainersName());
        map.put("containerPort",compose.getContainerPort());
        map.put("mountPath",compose.getMountPath());
        map.put("requestsMemory",compose.getRequestsMemory());
        map.put("resourcesCpu",compose.getResourcesCpu());
        map.put("limitsMemory",compose.getLimitsMemory());
        map.put("limitsCpu",compose.getLimitsCpu());
        map.put("portsPort",compose.getPortsPort());
        map.put("portsTargetPort",compose.getPortsTargetPort());
        map.put("proxyPath",compose.getProxyPath());
        map.put("proxyServicePort",compose.getProxyServicePort());
        //----------------------vendor.yaml----------------------
        map.put("bluetronId",vendor.getBluetronId()); //bluetronID
        map.put("organization",vendor.getOrganization()); //组织名称
        map.put("url",vendor.getUrl());//组织的网址
        map.put("email",vendor.getEmail());//邮箱
        map.put("copyright",vendor.getCopyright());//copyright
        map.put("address",vendor.getAddress());//地址
        //----------------------Dockerfile----------------------
//            map.put("jarFile",projectName + "-" + projectVersion + "." + packageing);
        map.put("jarFile",app.getName() + "-" + app.getAppVersion() + "." + packageing);
        //Dockerfile基础镜像
        map.put("baseDockerImage",other.getBaseDockerImage());
        try {
            String osName = System.getProperty("os.name");
            System.out.println("os name :" + osName);
            String jarPath = Generate.class.getResource("/freemarker").getFile();
            System.out.println("pre jarPath :" + jarPath);
            //判断操作系统，Windows和Linux的文件路径有所区别
            if (StringUtils.contains(osName,"Linux") || StringUtils.contains(osName,"Mac")){
                jarPath = jarPath.replaceAll("file:","").replaceAll("!/freemarker","");
            } else if (StringUtils.contains(osName,"Windows")){
                jarPath = jarPath.replaceAll("file:/","").replaceAll("!/freemarker","");
            }
            System.out.println("jarPath : " + jarPath);

            //从Jar包中复制ftl文件到项目目录下面
            copyFileFromJar(jarPath,".ftl",projectPath);

            //创建bin目录
            String binPath = projectPath + "bin";
            File binFile = new File(binPath);
            if (!binFile.exists()){
                binFile.mkdirs();
            }
            //创建data目录
            String dataPath = projectPath + "data";
            File dataFile = new File(dataPath);
            if (!dataFile.exists()){
                dataFile.mkdirs();
            }

            //遍历生成配置文件
            File[] freemarkerFiles = new File(projectPath + "freemarker").listFiles();
            if (null != freemarkerFiles && freemarkerFiles.length > 0) {
                for (File freemarkerFile : freemarkerFiles) {
                    //设置默认后缀
                    String suffix = DEFAULT_SUFFIX;
                    String filePath = projectPath;
                    String fileName = freemarkerFile.getName();
                    String filePrefix = fileName.split("\\.")[0];
                    if ("Dockerfile".equals(filePrefix)){
                        //如果是Dockerfile 后缀去掉
                        suffix = "";
                        filePath = binPath + File.separator;
                    } else if ("config".equals(filePrefix)){
                        //config.ini 后缀为.ini
                        suffix = ".ini";
                    } else if ("resource".equals(filePrefix)){
                        //如果是resource.yaml 在data目录里生成
                        filePath = dataPath + File.separator;
                    }
                    FreemarkerUtil.deploy(map, filePath + filePrefix + suffix, "", freemarkerFile.getName());
                }
            }
            //最后删除模板文件夹
            deleteAllFilesOfDir(new File(projectPath + "/freemarker"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @function 读取jar包中指定文件的内容并且将读取到的内容拷贝到指定目录中
     * @param jarPath jar文件的路径
     * @param name 要读取的文件名称，要添加后缀名
     * @param toPath 将拷贝到的信息复制到目标目录
     */
    public static void copyFileFromJar(String jarPath , String name, String toPath) {
        InputStream is = null;
        BufferedReader br = null;
        BufferedWriter bw = null;
        OutputStreamWriter oStreamWriter = null;
        try {
            JarFile jf = new JarFile(jarPath);
            Enumeration<JarEntry> jfs = jf.entries();
            while (jfs.hasMoreElements()) {
                JarEntry jfn = jfs.nextElement();
                if (jfn.getName().endsWith(name)) {
                    System.out.println(jfn.getName());
                    is = jf.getInputStream(jfn);
                    File file = new File(toPath + jfn.getName());
                    if (!file.exists()) {
                        file.getParentFile().mkdirs();
                    }
                    br = new BufferedReader(new InputStreamReader(is));
                    bw = new BufferedWriter(new FileWriter(file));
                    oStreamWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
                    String line = null;
                    while((line = br.readLine()) != null){
                        oStreamWriter.append(new String(line.getBytes(), StandardCharsets.UTF_8));
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
                if (null != br) {
                    is.close();
                }
                if (null != bw) {
                    is.close();
                }
                if (null != oStreamWriter) {
                    oStreamWriter.close();
                }
            } catch (IOException ignored) {

            }
        }
    }

    /**
     * 删除文件夹（强制删除）
     *
     * @param path
     */
    private static void deleteAllFilesOfDir(File path) {
        if (null != path) {
            if (!path.exists())
                return;
            if (path.isFile()) {
                boolean result = path.delete();
                int tryCount = 0;
                while (!result && tryCount++ < 10) {
                    System.gc(); // 回收资源
                    result = path.delete();
                }
            }
            File[] files = path.listFiles();
            if (null != files) {
                for (int i = 0; i < files.length; i++) {
                    deleteAllFilesOfDir(files[i]);
                }
            }
            path.delete();
        }
    }
}
